OAsm Preprocessor

The OAsm preprocessor is a C preprocessor, with extensions. The preprocessor can be considered to be a set of routines which go through the code before it is assembled, making certain types of textual transformations to the source code. The transformations range from simple substitution of text or lines of text when a keyword is encountered, to inclusion of text from another file, to selectively ignoring some lines based on compile-time settings. The main difference from a C preprocessor, other than the extensions, is that instead of starting a preprocessor directive with a hash ('#') preprocessor directives are started with a percent ('%').

Many of these directives involve Conditional Processing, which is a way to selectively choose what lines of code to assemble and what lines to ignore based on previous declarations.

Table 1 shows the C-style preprocessor directives. These directives are compatible with similar directives in a C Compiler's preprocessor.

Directive Usage
%define define a constant or function-style macro
%undef undefine a macro
%error display an error
%line set the file and line displayed in error messages
%include include another file
%if conditional which tests for nonzero expression
%elif else-style conditional which tests for nonzero-expression
%ifdef conditional which tests to see if a macro has been %defined
%ifndef conditional which tests to see if a macro has not been %defined
%else else clause for conditionals
%endif end of conditional

Table 1 - C lanuage style preprocessor directives

Table 2 shows basic extensions to the C preprocessor that are similar to directives already found in the preprocessor. This includes a new directive %assign which is like %define except it evaluates the macro value on the assumption it is a numeric expression. It also includes case insensitive macro definition directives, and the beginning of an extensive set of extensions to condtionals that are similar to the %elif mechanism.

Directive Usage
%assign Like %define, but evaluates an expression and sets the value to the result
%iassign %assign with a case-insensitive name
%idefine %define with a case-insensitive name
%elifdef else-style conditional which tests to see if a macro has been %defined
%elifndef else-style conditional which tests to see if a macro has not been %defined

Table 2 - Basic extensions to C style preprocessor

Table 3 shows extensions to the conditional mechanism that allow text comparisons. There are both case sensitive and case insensitive forms of these directives.

Conditional Directive Usage
%ifidn Case sensitive test for string matching
%ifnidn Case sensitive test for string not matching
%elifidn else-style case sensitive test for string matching
%elifnidn else-style case sensitive test for string not matching
%ifidni Case insensitive test for string matching
%ifnidni Case insensitive test for string not matching
%elifndi else-style case insensitive test for string matching
%elifnidni else-style case insensitive test for string not matching

Table 3 - Text Comparison Conditionals

Table 4 shows various extensions to the conditional mechanism that allow classification of a token's type. They can be used for example in multiline macros, to allow a single macro to have different behaviors based on the type of a macro argument.

Conditional Directive Usage
%ifid test to see if argument is an identifier
%ifnid test to see if argument is not an identifier
%elifid else-style test to see if argument is an identifier
%elifnid else-style test to see if argument is not an identifier
%ifnum test to see if argument is a number
%ifnnum test to see if argument is not a number
%elifnum else-style test to see if argument is a number
%elifnnum else-style test to see if argument is not a number
%ifstr test to see if argument is a string
%ifnstr test to see if argument is not a string
%elifstr else-style test to see if argument is a string
%elifnstr else-style test to see if argument is not a string

Table 4 - Token Type Classification Conditionals

Table 5 shows the Multiline Macro Extensions. and the Repeat Block Extensions. These extentions include multiline macros, as well as a powerful facility for using the preprocessor to repeat sections of code or data.

Directive Usage
%macro start a multiline macro
%imacro start a multiline macro, case insensitive name
%endmacro end a multiline macro
%rotate rotate arguments in a multiline macro
%rep start a repeat block
%endrep end a repeat block
%exitrep exit a repeat block prematurely

Table 5 - Multiline Macro and Repeat Block Extensions

Table 6 shows the Context-Related Extensions. Preprocessor contexts are a powerful mechanism that can be used to 'remember' data between successive macro invocations, and for example could be used to construct a high-level representation of control constructs in the assembler.

Directive Usage
%push start a new context
%pop end a new context
%repl rename the context at the tope of the context stack
%ifctx test to see if a context is in effect
%ifnctx test to see if a context is not in effect
%elifctx else-style test to see if a context is in effect
%elifnctx else-style test to see if a context is not in effect

Table 6 - Context - Related Extensions